import 'dart:async';

import 'package:analyzer/dart/constant/value.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/type.dart';
import 'package:build/build.dart' hide log;
import 'package:source_gen/source_gen.dart';
import 'package:sqliteasy_core/sqliteasy_core.dart';
import '../log.dart';
import '../model/code_fragment.dart';
import '../model/database.dart';
import '../util/dao_generator.dart';
import '../util/database_util.dart';
import '../util/generators/database_gen.dart';
import '../util/generators/value_converter_gen.dart';

/// @author: dealin
/// created at 2020/12/30 21:01

class DatabaseBuilder extends Generator {
  static final _tag = "DatabaseGenerator";
  FutureOr<String> generate(LibraryReader library, BuildStep buildStep) {
    var databaseList = library.annotatedWith(TypeChecker.fromRuntime(Database));
    if (databaseList.isEmpty) {
      return null;
    }
    final databaseFragments = List<CodeFragment>.empty(growable: true);
    final daoFragments = List<CodeFragment>.empty(growable: true);
    final valueConverterFragments = List<CodeFragment>.empty(growable: true);
    final daoGenerators = List<DaoGenerator>.empty(growable: true);
    databaseList.forEach((element) {
      if (element.annotation.objectValue == null) {
        return;
      }
      ClassElement databaseElement = element.element as ClassElement;
      DatabaseInfo databaseInfo = DatabaseUtil.getDatabaseInfoFromElement(databaseElement);
      final daoGenerator = DaoGenerator(databaseInfo);
      daoGenerators.add(daoGenerator);

      Set<MethodElement> daoGetters = Set();
      Set<String> generatedDaoSet = Set();
      // 解析DaoGetter
      databaseElement.methods.forEach((methodElement) {
        Element returnElement = methodElement.returnType.element;
        if (DatabaseUtil.isDaoClass(returnElement) && methodElement.parameters.isEmpty) {
          // 生成代码
          log(_tag, "生成Dao相关代码");
          if (!generatedDaoSet.contains(returnElement.name)) {
            daoFragments.add(daoGenerator.genDaoCode(returnElement));
            generatedDaoSet.add(returnElement.name);
          }
          daoGetters.add(methodElement);
        }
      });

      // 生成ValueConverter
      Set<DartType> generatedEntitySet = Set();
      daoGenerators.forEach((element) {
        element.valueConverterEntitySet.forEach((entityType) {
          if (generatedEntitySet.contains(entityType)) {
            return;
          }
          final codeFrag = ValueConverterGenerator.genImpl(entityType);
          if (codeFrag == null) {
            return;
          }
          valueConverterFragments.add(codeFrag);
        });
      });
      databaseFragments.add(DatabaseCodeGenerator.gen(databaseInfo, daoGetters));
    });
    Set<String> importComponents = Set();
    databaseFragments.forEach((element) {
      importComponents.addAll(element?.importList ?? []);
    });
    daoFragments.forEach((element) {
      importComponents.addAll(element?.importList ?? []);
    });
    // valueConverterFragments.forEach((element) {
    //   importComponents.addAll(element?.importList ?? []);
    // });
    log("database_builder", "输出代码");
    final content = (databaseFragments.map((e) => e.content).join("\n\n"))
        + "\n\n/// ==========DaoImpl==========\n" + (daoFragments.map((e) => e.content)).join("\n\n")
        + "\n\n/// ==========ValueConverters==========\n" + valueConverterFragments.map((e) => e.content).join("\n\n");
    return "${importComponents.map((e) => "import \"$e\";\n").join()}${content}";
  }

}
